#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
COS上传器
负责文件上传到腾讯云COS和CDN管理
"""

import os
import logging
import hashlib
import time
from typing import Optional, Dict
from datetime import datetime, timedelta

try:
    from qcloud_cos import CosConfig
    from qcloud_cos import CosS3Client
    COS_AVAILABLE = True
except ImportError:
    COS_AVAILABLE = False
    logging.warning("qcloud_cos未安装，COS功能不可用")

logger = logging.getLogger(__name__)

class COSUploader:
    def __init__(self):
        self.client = None
        self.bucket_name = None
        self.region = None
        self.cdn_domain = None
        self._init_cos_client()
    
    def _init_cos_client(self):
        """初始化COS客户端"""
        if not COS_AVAILABLE:
            logger.warning("COS SDK未安装，使用模拟模式")
            return
        
        try:
            # 从环境变量获取配置
            secret_id = os.getenv('COS_SECRET_ID')
            secret_key = os.getenv('COS_SECRET_KEY')
            region = os.getenv('COS_REGION', 'ap-guangzhou')
            bucket_name = os.getenv('COS_BUCKET_NAME')
            cdn_domain = os.getenv('CDN_DOMAIN')
            
            if not all([secret_id, secret_key, bucket_name]):
                logger.warning("COS配置不完整，使用模拟模式")
                return
            
            # 创建COS配置
            config = CosConfig(
                Region=region,
                SecretId=secret_id,
                SecretKey=secret_key
            )
            
            # 创建COS客户端
            self.client = CosS3Client(config)
            self.bucket_name = bucket_name
            self.region = region
            self.cdn_domain = cdn_domain
            
            logger.info(f"COS客户端初始化成功: {bucket_name} ({region})")
            
        except Exception as e:
            logger.error(f"COS客户端初始化失败: {str(e)}")
            self.client = None
    
    def is_available(self) -> bool:
        """检查COS是否可用"""
        return self.client is not None
    
    def upload_file(self, local_file_path: str, object_key: str, 
                   content_type: str = 'image/jpeg') -> Optional[str]:
        """
        上传文件到COS
        
        Args:
            local_file_path: 本地文件路径
            object_key: COS对象键
            content_type: 文件类型
            
        Returns:
            str: COS URL或None
        """
        if not self.is_available():
            logger.warning("COS不可用，返回模拟URL")
            return f"https://mock-cos.com/{object_key}"
        
        try:
            # 检查文件是否存在
            if not os.path.exists(local_file_path):
                logger.error(f"文件不存在: {local_file_path}")
                return None
            
            # 获取文件大小
            file_size = os.path.getsize(local_file_path)
            logger.info(f"上传文件: {local_file_path} -> {object_key} ({file_size} bytes)")
            
            # 上传文件
            with open(local_file_path, 'rb') as f:
                response = self.client.put_object(
                    Bucket=self.bucket_name,
                    Body=f,
                    Key=object_key,
                    ContentType=content_type
                )
            
            if response:
                # 构建COS URL
                cos_url = f"https://{self.bucket_name}.cos.{self.region}.myqcloud.com/{object_key}"
                logger.info(f"文件上传成功: {cos_url}")
                return cos_url
            else:
                logger.error("文件上传失败")
                return None
                
        except Exception as e:
            logger.error(f"上传文件异常: {str(e)}")
            return None
    
    def upload_enhanced_image(self, local_file_path: str, task_id: str) -> Optional[str]:
        """
        上传增强后的图片
        
        Args:
            local_file_path: 本地文件路径
            task_id: 任务ID
            
        Returns:
            str: CDN URL或None
        """
        try:
            # 生成对象键
            timestamp = int(time.time())
            object_key = f"enhanced/{timestamp}_{task_id}.jpg"
            
            # 上传到COS
            cos_url = self.upload_file(local_file_path, object_key, 'image/jpeg')
            
            if cos_url and self.cdn_domain:
                # 如果有CDN域名，返回CDN URL
                cdn_url = f"https://{self.cdn_domain}/{object_key}"
                logger.info(f"CDN URL: {cdn_url}")
                return cdn_url
            else:
                # 否则返回COS URL
                return cos_url
                
        except Exception as e:
            logger.error(f"上传增强图片异常: {str(e)}")
            return None
    
    def generate_presigned_url(self, object_key: str, 
                              expires_in: int = 3600) -> Optional[str]:
        """
        生成预签名URL
        
        Args:
            object_key: COS对象键
            expires_in: 过期时间(秒)
            
        Returns:
            str: 预签名URL或None
        """
        if not self.is_available():
            return None
        
        try:
            response = self.client.get_presigned_download_url(
                Bucket=self.bucket_name,
                Key=object_key,
                Expired=expires_in
            )
            
            return response
            
        except Exception as e:
            logger.error(f"生成预签名URL异常: {str(e)}")
            return None
    
    def delete_file(self, object_key: str) -> bool:
        """
        删除COS文件
        
        Args:
            object_key: COS对象键
            
        Returns:
            bool: 删除是否成功
        """
        if not self.is_available():
            return False
        
        try:
            response = self.client.delete_object(
                Bucket=self.bucket_name,
                Key=object_key
            )
            
            logger.info(f"文件删除成功: {object_key}")
            return True
            
        except Exception as e:
            logger.error(f"删除文件异常: {str(e)}")
            return False
    
    def list_files(self, prefix: str = "", max_keys: int = 100) -> list:
        """
        列出COS文件
        
        Args:
            prefix: 对象键前缀
            max_keys: 最大返回数量
            
        Returns:
            list: 文件列表
        """
        if not self.is_available():
            return []
        
        try:
            response = self.client.list_objects(
                Bucket=self.bucket_name,
                Prefix=prefix,
                MaxKeys=max_keys
            )
            
            files = []
            if 'Contents' in response:
                for obj in response['Contents']:
                    files.append({
                        'key': obj['Key'],
                        'size': obj['Size'],
                        'last_modified': obj['LastModified'],
                        'etag': obj['ETag']
                    })
            
            return files
            
        except Exception as e:
            logger.error(f"列出文件异常: {str(e)}")
            return []
    
    def cleanup_old_files(self, prefix: str = "enhanced/", 
                         max_age_hours: int = 24) -> int:
        """
        清理旧文件
        
        Args:
            prefix: 对象键前缀
            max_age_hours: 最大保存时间(小时)
            
        Returns:
            int: 删除的文件数量
        """
        try:
            files = self.list_files(prefix)
            max_age = timedelta(hours=max_age_hours)
            current_time = datetime.now()
            
            deleted_count = 0
            for file_info in files:
                # 解析最后修改时间
                last_modified = datetime.strptime(
                    file_info['last_modified'], 
                    '%Y-%m-%dT%H:%M:%S.%fZ'
                )
                
                # 检查是否过期
                if current_time - last_modified > max_age:
                    if self.delete_file(file_info['key']):
                        deleted_count += 1
            
            logger.info(f"清理了 {deleted_count} 个过期文件")
            return deleted_count
            
        except Exception as e:
            logger.error(f"清理旧文件异常: {str(e)}")
            return 0
